<?php
/**
 * clase_zen_POA_Tejedora.php
 * @author Juan Belon
 * @access public
 * @copyright LGPL, GPL
 * @package zen_POA
 * @version 0.1.1
 * @uses zenphp FrameWork
 * @link http://csl2-zenphp.forja.rediris.es
 * @link http://www.zenphp.es
 * @link https://forja.rediris.es/projects/csl2-zenphp/
 * @magic Generadora de aspectos a anotar en ficheros de XML (XAD) a PHP   [WEAVER]
 * TODO: Completar la Documentación de las clases de POA
 */
// +----------------------------------------------------------------------
// | zenphp.es
// +----------------------------------------------------------------------

require_once "clase_zen_POA_Aspecto.php";
require_once "clase_zen_POA_Anotador.php";


class zen_POA_Tejedora
{
	var $_inicializada;
	var $_ultima_modificacion;
	var $_aspectos;
	var $__directorios;


	function zen_POA_Tejedora()
	{
		$this->_aspectos = array();
		$this->__directorios = array();

		$this->_inicializada = false;
		$this->_ultima_modificacion = 0;

		// Cargar aspectos
		$numArgs = func_num_args();

		for ($i = 0; $i < $numArgs; $i++) {
			$arg =& func_get_arg($i);
			$this->_manejadorCarga($arg);
		}
	}


	function insertarAspecto(&$aspecto)
	{
		if (is_a($aspecto, "zen_POA_Aspecto")) {
			$this->_aspectos[count($this->_aspectos)] =& $aspecto;

			// Analizar el aspecto recién modificado/añadido
			if ($this->_ultima_modificacion < $aspecto->obtenerUltimaModificacion()) {
                $this->_ultima_modificacion = $aspecto->obtenerUltimaModificacion();
			}

			return true;
		}

		return false;
	}


	function & obtenerAspecto($i)
	{
    	if ($this->_inicializada === false) {
			$this->inicializar();
		}

		if (array_key_exists($i, $this->_aspectos)) {
			return $this->_aspectos[$i];
		}

		return null;
	}
	
	
	function &obtenerAspectos()
	{
		if ($this->_inicializada === false) {
			$this->inicializar();
		}

		return $this->_aspectos;
	}


	function obtenerInicializacion() { return $this->_inicializada; }

	function obtenerUltimaModificacion() { return $this->_ultima_modificacion; }
	
	
	function tieneAspectos()
	{
    	// Provee una carga perezosa (no es demasiado eficiente :O )
		if ($this->_inicializada === false) {
    		if (count($this->__directorios) > 0) {
    			return true;
			}

			if (count($this->_aspectos) > 0) {
				return true;
			}
    	}

    	return ($this->obtenerTamanio() > 0) ? true : false;
	}
	
	
	function obtenerTamanio()
	{
    	if ($this->_inicializada === false) {
			$this->inicializar();
		}
		
		return count($this->_aspectos);
	}


	function inicializar()
	{
		if (($l = count($this->__directorios)) > 0) {
			for ($i = 0; $i < $l; $i++) {
				$pos = $this->__directorios[$i]["posicion"];
				$dir = $this->__directorios[$i]["directorio"];
				
				$this->_leerDirectorio($dir, $pos);
			}
		}

		// Cambiar la bandera de carga:
		$this->_inicializada = true;
	}
	
	
	function _leerDirectorio($dir, &$pos)
	{
    	// Abrir el directorio con el manejador
		$manejador = dir($dir);

		// Iteramos el directorio
		while (false !== ($fichero = $manejador->read())) {
			// Si no es un alias del SO:
			if ($fichero != "." && $fichero != "..") {
				$fichero = $dir . "/" . $fichero;

                // Es un directorio?
				if (is_dir($fichero)) {
					$this->_leerDirectorio($fichero, $pos);
				// Es un fichero XML? (formato XAD)
				} else {
					$ruta = pathinfo($fichero);
					$mime = mime_content_type($fichero);

					if (($mime != "" && $mime == "text/xml") ||
						(is_readable($fichero) && $ruta["extension"] == "xml")) {
						// Cargar el aspecto!:
						$aspecto =& zen_POA_Aspecto::cargar($fichero);
                        
						// Definirlo en la lista de Aspectos
						// La posici?n es relativa a la definida desde el constructor de la clase zen_POA_Tejedora
						// array_splice reemplaza los objetos->Como dice el manual, se pasan a trav?s de un array:
						array_splice($this->_aspectos, $pos++, 0, array($aspecto));
					}
				}
			}
		}

		// Cerrar el manejador de directorio
		$manejador->close();
	}


	function _manejadorCarga(&$item)
	{
		// Si el argumento pasado es un objeto zen_POA_Aspecto
		if (is_a($item, "zen_POA_Aspecto")) {
			$this->insertarAspecto($item);
		// Es un array?
		} elseif (is_array($item)) {
			$l = count($item);

			for ($i = 0; $i < $l; $i++) {
				$arg =& $item[$i];
				$this->_manejadorCarga($arg);
			}
		// Un directorio?
		} elseif (is_string($item) && is_dir($item)) {
			// Un directorio puede contener m?s de un fichero
			// Prevenimos al servidor de sobrecargas innecesarias...
			$i = count($this->__directorios);

			$this->__directorios[$i]["posicion"] = count($this->_aspectos);
            $this->__directorios[$i]["directorio"] = realpath($item);

            // Comprobar la ?ltima modificaci?n (fichero?)
            $modificacion = filemtime($this->__directorios[$i]["directorio"]);

			if ($this->_ultima_modificacion < $modificacion) {
                $this->_ultima_modificacion = $modificacion;
			}
		// Es un XML de aspectos? (XAD)
		} elseif (is_string($item) && is_file($item)) {
			// Cargar el aspecto
			$aspecto =& zen_POA_Aspecto::cargar($item);

			// Insertarlo en la Tejedora de C?digo
			$this->insertarAspecto($aspecto);
		}
	}


	/**
    * @desc A?adido
    */
	function &obtenerAnotadorDePuntoCortePropio($nombre_clase, $nombre_funcion, $nombre_puntocorte)
	{
		$notacion =& new zen_POA_Anotador();
		
		$aspectos =& $this->obtenerAspectos();
		$l = count($aspectos);

		for ($i = 0; $i < $l; $i++) {
			$aspecto =& $this->_aspectos[$i];

			$a =& $aspecto->obtenerAnotadorDePuntoCortePropio(
				$nombre_clase, $nombre_funcion, $nombre_puntocorte
			);

			$notacion->insertarContenido($a->obtenerContenido());
		}

		return $notacion;
	}


	function &obtenerAnotadorDePuntoCorteAuto($nombre_clase, $nombre_funcion, $nombre_puntocorte_auto)
	{
		$notacion =& new zen_POA_Anotador();
		
		$aspectos =& $this->obtenerAspectos();
		$l = count($aspectos);

		for ($i = 0; $i < $l; $i++) {
			$aspecto =& $this->_aspectos[$i];

			$a =& $aspecto->obtenerAnotadorDePuntoCorteAuto(
				$nombre_clase, $nombre_funcion, $nombre_puntocorte_auto
			);

			$notacion->insertarContenido($a->obtenerContenido());
		}

		return $notacion;
	}
}

?>